home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 1.toast / Sample Code / Contributed / SpriteWorld / SpriteWorld Files / Utils / Brian's Extensions / BlitPixieScaled.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-10-06  |  60.5 KB  |  2,150 lines  |  [TEXT/CWIE]

  1. /*  -----------------------------------------------------------------------------------
  2.     -----------------------------------------------------------------------------------
  3.     BlitPixieScaled.c
  4.     
  5.     by Brian Roddy, 5/31/97
  6.     
  7.     Bug fixes by Vern Jensen, 12/7/98. Optimizations by Vern Jensen 2/7/99.
  8.     
  9.     Change in scanLinePtrArray lookup and addition of 32-bit routine by afb.
  10.     
  11.     These routines are blitters that dynamically shrink or stretch the sprite. These 
  12.     routines work in 8-bits, 16-bits, and 32-bits.
  13.     
  14.     Use SWSetSpriteScaledSize to set the scaling size.  When the sprite is drawn, it
  15.     will be stretched or shrunk to the new width and height you specify.  
  16.     SWSetSpriteScaledSize takes a sprite pointer and a width and a height.  e.g.:
  17.     
  18.      SWSetSpriteScaledSize(mySpritePtr, 20, 50);  // Scale it
  19.     
  20.     Use a width or height <= 0 to turn off scaling.  Note that just resetting 
  21.     the sprite's draw procedure will not turn off scaling properly.  Make sure to 
  22.     call SWSetSpriteScaledSize with a negative width or height.  e.g.:
  23.  
  24.      SWSetSpriteScaledSize(mySpritePtr, -1, -1);  // Reset it back to normal
  25.      
  26.      The maximum scaled width is 1280. Values larger than this are permissible as long as the Sprite
  27.      is clipped so that the visible portion of the Sprite after being clipped is no larger than 1280.
  28.      For instance, if your SpriteWorld's window is 1280 pixels wide and your Sprites are clipped
  29.      to that window, then your may scale your Sprites larger than 1280 pixels. Otherwise, you will
  30.      get an assertion error if you try to scale them larger. You can get around this limitation
  31.      if necessary; simply change the definition of kMaxScaledWidth at the beginning of 
  32.      BlitPixieScaled.c to any value, and your Sprites can then be scaled to that maximum size.
  33.      There is no maximum scaled height; your height can be any size.
  34.      
  35.     Also note that scaling is done while drawing to the screen.  As a result, the
  36.     pixels in the frames don't match what shows up on the screen.  This means that 
  37.     functions which rely on the sprite's mask, such as SWPixelCollision, won't work as 
  38.     expected.  Thus using the pixel or mask collision routines with scaled sprites 
  39.     won't work accurately.
  40.     
  41.     SWSetSpriteScaledSize sets the scaling DrawProc for you automatically, so you don't 
  42.     need to call SWSetSpriteDrawProc, unless you want to use a RectDrawProc instead of the 
  43.     automatically assigned ScaledMaskDrawProc. It will also change the DrawProc back to one
  44.     of the standard BlitPixieMaskDrawProcs when you set the scaled size to -1 to turn off
  45.     scaling. Here is a list of the available DrawProcs:
  46.     
  47.         // User DrawProcs:
  48.     BlitPixie8BitScaledRectDrawProc
  49.     BlitPixie16BitScaledRectDrawProc
  50.     
  51.         // Sprite DrawProcs:
  52.     BP8BitScaledSpriteRectDrawProc
  53.     BP8BitScaledSpriteMaskDrawProc
  54.     BP16BitScaledSpriteRectDrawProc
  55.     BP16BitScaledSpriteMaskDrawProc
  56.     
  57.     The User DrawProcs are available for you to use directly if you want to do some direct
  58.     scaling, such as scaling the contents of the work area as you copy it to the screen.
  59.     The Sprite DrawProcs are what you should use when assigning a Sprite a scaling
  60.     DrawProc. Do not get these two types of DrawProcs mixed up.
  61.     
  62.     
  63.     -----------------------------------------------------------------------------------
  64.     Implementation Notes:
  65.  
  66.     These blitters use the "Bresenham line drawing algorithm" to do the scaling.  This is
  67.     the standard technique used for many scaling and texture mapping algorithms.  Additionally,
  68.     the scaling data is pre-computed and stored in an array to speed up each line. In particular,
  69.     this allows much faster blitting of shrunk Sprites, clipped Sprites, and direct-to-screen
  70.     scaling.
  71.     
  72.     This source code is available for free use.
  73.  
  74.     ----------------------------------------------------------------------------------- 
  75.     ----------------------------------------------------------------------------------- */
  76.  
  77.  
  78. #include <BlitPixieScaled.h>
  79.  
  80. #define kMaxScaledWidth            1280            // Change this to a larger value if necessary
  81.  
  82.     // The following variables are used by PrecomputeLookupTable
  83. static short            gSrcLeftClip,
  84.                         gNumPixelsToCopy;
  85. static unsigned short    gLookupArray[kMaxScaledWidth];
  86.  
  87.  
  88. #pragma mark ----------- Public API -------------
  89.  
  90. ///--------------------------------------------------------------------------------------
  91. //    SWSetSpriteScaledSize
  92. ///--------------------------------------------------------------------------------------
  93.  
  94. SW_FUNC OSErr SWSetSpriteScaledSize(
  95.     SpritePtr srcSpriteP,
  96.     short width,
  97.     short height) 
  98. {
  99.     short         currentPixelDepth;
  100.     OSErr        err = noErr;
  101.     
  102.     
  103.     currentPixelDepth = srcSpriteP->frameArray[0]->frameDepth;
  104.     
  105.     if (currentPixelDepth == 8)
  106.     {
  107.         if ((width <= 0) || (height <= 0))
  108.         {
  109.             srcSpriteP->scaledWidth = -1;
  110.             srcSpriteP->scaledHeight = -1;
  111.             srcSpriteP->frameDrawProc = BlitPixieMaskDrawProc;
  112.         } 
  113.         else
  114.         {
  115.             srcSpriteP->scaledWidth = width;
  116.             srcSpriteP->scaledHeight = height;
  117.             srcSpriteP->frameDrawProc = BP8BitScaledSpriteMaskDrawProc;
  118.         }
  119.     }
  120.     else if (currentPixelDepth == 16)
  121.     {
  122.         if ((width <= 0) || (height <= 0))
  123.         {
  124.             srcSpriteP->scaledWidth = -1;
  125.             srcSpriteP->scaledHeight = -1;
  126.             srcSpriteP->frameDrawProc = BlitPixieMaskDrawProc;
  127.         } 
  128.         else
  129.         {
  130.             srcSpriteP->scaledWidth = width;
  131.             srcSpriteP->scaledHeight = height;
  132.             srcSpriteP->frameDrawProc = BP16BitScaledSpriteMaskDrawProc;
  133.         }
  134.     }
  135.     else if (currentPixelDepth == 32)
  136.     {
  137.         if ((width <= 0) || (height <= 0))
  138.         {
  139.             srcSpriteP->scaledWidth = -1;
  140.             srcSpriteP->scaledHeight = -1;
  141.             srcSpriteP->frameDrawProc = BlitPixieMaskDrawProc;
  142.         } 
  143.         else
  144.         {
  145.             srcSpriteP->scaledWidth = width;
  146.             srcSpriteP->scaledHeight = height;
  147.             srcSpriteP->frameDrawProc = BP32BitScaledSpriteMaskDrawProc;
  148.         }
  149.     }
  150.     else
  151.     {    
  152.         err = kWrongDepthErr;
  153.     }
  154.     if (err == noErr)
  155.     {
  156.             // Force a refresh of the sprite in the case of sprites with one frame
  157.         SWSetCurrentFrameIndex(srcSpriteP, srcSpriteP->curFrameIndex);
  158.     }
  159.     
  160.     SWSetStickyIfError( err );
  161.     return err;
  162. }
  163.  
  164. ///--------------------------------------------------------------------------------------
  165. //    SWGetSpriteScaledWidth
  166. ///--------------------------------------------------------------------------------------
  167.  
  168. SW_FUNC short SWGetSpriteScaledWidth(
  169.     SpritePtr srcSpriteP)
  170. {
  171.     return srcSpriteP->scaledWidth;
  172. }
  173.  
  174. ///--------------------------------------------------------------------------------------
  175. //    SWGetSpriteScaledHeight
  176. ///--------------------------------------------------------------------------------------
  177.  
  178. SW_FUNC short SWGetSpriteScaledHeight(
  179.     SpritePtr srcSpriteP)
  180. {
  181.     return srcSpriteP->scaledHeight;
  182. }
  183.  
  184.  
  185.  
  186. ///--------------------------------------------------------------------------------------
  187. /// BLITTERS
  188. ///--------------------------------------------------------------------------------------
  189.  
  190. #pragma mark ----------- 8 Bit Blitters -------------
  191. ///--------------------------------------------------------------------------------------
  192. //    BlitPixie8BitScaledRectDrawProc - doesn't "unclip" the source rect, so it
  193. //    can be used directly by the user.
  194. ///--------------------------------------------------------------------------------------
  195.  
  196. SW_FUNC void BlitPixie8BitScaledRectDrawProc(
  197.     FramePtr srcFrameP,
  198.     FramePtr dstFrameP,
  199.     Rect* srcRect,
  200.     Rect* dstRect)
  201. {
  202.     Rect         srcBlitRect = *srcRect;
  203.     Rect         dstBlitRect = *dstRect;
  204.     short        topClip, rightClip, bottomClip, leftClip;
  205.     
  206.     SW_ASSERT(srcFrameP->isFrameLocked && dstFrameP->isFrameLocked);
  207.     SW_ASSERT(srcFrameP->frameDepth == 8 && dstFrameP->frameDepth == 8);
  208.  
  209.         // Make sure some part of the Sprite is inside the dstFrame
  210.     if (dstBlitRect.left >= dstFrameP->frameRect.right ||
  211.         dstBlitRect.right <= dstFrameP->frameRect.left ||
  212.         dstBlitRect.top >= dstFrameP->frameRect.bottom ||
  213.         dstBlitRect.bottom <= dstFrameP->frameRect.top )
  214.     {
  215.         return;
  216.     }
  217.  
  218.     topClip = rightClip = bottomClip = leftClip = 0;
  219.     
  220.         // Clip dstRect with dstFrameP->frameRect
  221.     if (dstBlitRect.top < dstFrameP->frameRect.top)
  222.     {
  223.         topClip = dstFrameP->frameRect.top - dstBlitRect.top;
  224.         dstBlitRect.top = dstFrameP->frameRect.top;
  225.     }
  226.     
  227.     if (dstBlitRect.bottom > dstFrameP->frameRect.bottom)
  228.         bottomClip = dstBlitRect.bottom - dstFrameP->frameRect.bottom; 
  229.     
  230.     if (dstBlitRect.left < dstFrameP->frameRect.left)
  231.         leftClip = dstFrameP->frameRect.left - dstBlitRect.left;
  232.     
  233.     if (dstBlitRect.right > dstFrameP->frameRect.right)
  234.         rightClip = dstBlitRect.right - dstFrameP->frameRect.right;
  235.     
  236.     START_32_BIT_MODE
  237.     
  238.     PrecomputeLookupTable(
  239.         (srcBlitRect.right - srcBlitRect.left),
  240.         (dstBlitRect.right - dstBlitRect.left),
  241.         leftClip, 
  242.         rightClip);
  243.  
  244.  
  245.     BlitPixie8BitScaled(
  246.             // calculate the address of the first byte of the source
  247.         (unsigned char *)(srcFrameP->frameBaseAddr + 
  248.             (srcFrameP->scanLinePtrArray[srcBlitRect.top - srcFrameP->frameRect.top]) + 
  249.             srcBlitRect.left),
  250.  
  251.             // calculate the address of the first byte of the destination
  252.         (unsigned char *)(dstFrameP->frameBaseAddr + 
  253.             (dstFrameP->scanLinePtrArray[dstBlitRect.top - dstFrameP->frameRect.top]) + 
  254.             dstBlitRect.left),
  255.  
  256.             // calculate the number of rows to blit
  257.         (srcBlitRect.bottom - srcBlitRect.top),
  258.         (dstBlitRect.bottom - dstBlitRect.top) + topClip,
  259.  
  260.         srcFrameP->frameRowBytes,
  261.         dstFrameP->frameRowBytes,
  262.         
  263.             // clipping information
  264.         leftClip,
  265.         topClip,
  266.         bottomClip,
  267.         
  268.             // are we blitting direct-to-screen?
  269.         dstFrameP->isWindowFrame
  270.     );
  271.     
  272.  
  273.     END_32_BIT_MODE
  274. }
  275.  
  276.  
  277. ///--------------------------------------------------------------------------------------
  278. //    BP8BitScaledSpriteRectDrawProc
  279. ///--------------------------------------------------------------------------------------
  280.  
  281. SW_FUNC void BP8BitScaledSpriteRectDrawProc(
  282.     FramePtr srcFrameP,
  283.     FramePtr dstFrameP,
  284.     Rect* srcRect,
  285.     Rect* dstRect)
  286. {
  287.     Rect         srcBlitRect = *srcRect;
  288.     Rect         dstBlitRect = *dstRect;
  289.     short        topClip, rightClip, bottomClip, leftClip;
  290.     short        topClip2, rightClip2, bottomClip2, leftClip2;
  291.     
  292.     SW_ASSERT(srcFrameP->isFrameLocked && dstFrameP->isFrameLocked);
  293.     SW_ASSERT(srcFrameP->frameDepth == 8 && dstFrameP->frameDepth == 8);
  294.  
  295.         // Make sure some part of the Sprite is inside the dstFrame
  296.     if (dstBlitRect.left >= dstFrameP->frameRect.right ||
  297.         dstBlitRect.right <= dstFrameP->frameRect.left ||
  298.         dstBlitRect.top >= dstFrameP->frameRect.bottom ||
  299.         dstBlitRect.bottom <= dstFrameP->frameRect.top )
  300.     {
  301.         return;
  302.     }
  303.  
  304.     topClip = rightClip = bottomClip = leftClip = 0;
  305.     topClip2 = rightClip2 = bottomClip2 = leftClip2 = 0;
  306.     
  307.         // Clip dstRect with dstFrameP->frameRect
  308.     if (dstBlitRect.top < dstFrameP->frameRect.top)
  309.     {
  310.         topClip = dstFrameP->frameRect.top - dstBlitRect.top;
  311.         dstBlitRect.top = dstFrameP->frameRect.top;
  312.     }
  313.     
  314.     if (dstBlitRect.bottom > dstFrameP->frameRect.bottom)
  315.         bottomClip = dstBlitRect.bottom - dstFrameP->frameRect.bottom; 
  316.     
  317.     if (dstBlitRect.left < dstFrameP->frameRect.left)
  318.         leftClip = dstFrameP->frameRect.left - dstBlitRect.left;
  319.     
  320.     if (dstBlitRect.right > dstFrameP->frameRect.right)
  321.         rightClip = dstBlitRect.right - dstFrameP->frameRect.right;
  322.     
  323.     
  324.         // "Unclip" sprite if it was already clipped before this function was called
  325.     if (srcBlitRect.top > srcFrameP->frameRect.top)
  326.     {
  327.         topClip2 = srcBlitRect.top - srcFrameP->frameRect.top;
  328.         srcBlitRect.top = srcFrameP->frameRect.top;
  329.     }
  330.     
  331.     if (srcBlitRect.bottom < srcFrameP->frameRect.bottom)
  332.     {
  333.         bottomClip2 = srcFrameP->frameRect.bottom - srcBlitRect.bottom; 
  334.         srcBlitRect.bottom = srcFrameP->frameRect.bottom;
  335.         dstBlitRect.bottom += bottomClip2;
  336.     }
  337.  
  338.     if (srcBlitRect.left > srcFrameP->frameRect.left)
  339.     {
  340.         leftClip2 = srcBlitRect.left - srcFrameP->frameRect.left;
  341.         srcBlitRect.left = srcFrameP->frameRect.left;
  342.         dstBlitRect.left -= leftClip2;
  343.     }
  344.     
  345.     if (srcBlitRect.right < srcFrameP->frameRect.right)
  346.     {
  347.         rightClip2 = srcFrameP->frameRect.right - srcBlitRect.right; 
  348.         srcBlitRect.right = srcFrameP->frameRect.right;
  349.         dstBlitRect.right += rightClip2;
  350.     }    
  351.     
  352.     topClip += topClip2;
  353.     leftClip += leftClip2;
  354.     rightClip += rightClip2;
  355.     bottomClip += bottomClip2;
  356.         
  357.  
  358.     START_32_BIT_MODE
  359.     
  360.     PrecomputeLookupTable(
  361.         (srcBlitRect.right - srcBlitRect.left),
  362.         (dstBlitRect.right - dstBlitRect.left),
  363.         leftClip, 
  364.         rightClip);
  365.  
  366.  
  367.     BlitPixie8BitScaled(
  368.             // calculate the address of the first byte of the source
  369.         (unsigned char *)(srcFrameP->frameBaseAddr + 
  370.             (srcFrameP->scanLinePtrArray[srcBlitRect.top - srcFrameP->frameRect.top]) + 
  371.             srcBlitRect.left),
  372.  
  373.             // calculate the address of the first byte of the destination
  374.         (unsigned char *)(dstFrameP->frameBaseAddr + 
  375.             (dstFrameP->scanLinePtrArray[dstBlitRect.top]) + 
  376.             dstBlitRect.left),
  377.  
  378.             // calculate the number of rows to blit
  379.         (srcBlitRect.bottom - srcBlitRect.top),
  380.         (dstBlitRect.bottom - dstBlitRect.top) + topClip,
  381.  
  382.         srcFrameP->frameRowBytes,
  383.         dstFrameP->frameRowBytes,
  384.         
  385.             // clipping information
  386.         leftClip,
  387.         topClip,
  388.         bottomClip,
  389.         
  390.             // are we blitting direct-to-screen?
  391.         dstFrameP->isWindowFrame
  392.     );
  393.  
  394.  
  395.     END_32_BIT_MODE
  396. }
  397.  
  398. ///--------------------------------------------------------------------------------------
  399. //    BP8BitScaledSpriteMaskDrawProc
  400. ///--------------------------------------------------------------------------------------
  401.  
  402. SW_FUNC void BP8BitScaledSpriteMaskDrawProc(
  403.     FramePtr srcFrameP,
  404.     FramePtr dstFrameP,
  405.     Rect *srcRect,
  406.     Rect *dstRect)
  407. {
  408.     Rect                dstBlitRect = *dstRect;
  409.     Rect                srcBlitRect = *srcRect;
  410.     unsigned long         srcBaseOffset;
  411.     short                topClip, rightClip, bottomClip, leftClip;
  412.     short                topClip2, rightClip2, bottomClip2, leftClip2;
  413.     
  414.     SW_ASSERT(srcFrameP->isFrameLocked && dstFrameP->isFrameLocked);
  415.     SW_ASSERT(srcFrameP->frameDepth == 8 && dstFrameP->frameDepth == 8);
  416.     SW_ASSERT(srcFrameP->maskPort != NULL);
  417.  
  418.         // Make sure some part of the Sprite is inside the dstFrame
  419.     if (dstBlitRect.left >= dstFrameP->frameRect.right ||
  420.         dstBlitRect.right <= dstFrameP->frameRect.left ||
  421.         dstBlitRect.top >= dstFrameP->frameRect.bottom ||
  422.         dstBlitRect.bottom <= dstFrameP->frameRect.top )
  423.     {
  424.         return;
  425.     }
  426.  
  427.     topClip = rightClip = bottomClip = leftClip = 0;
  428.     topClip2 = rightClip2 = bottomClip2 = leftClip2 = 0;
  429.     
  430.         // Clip dstRect with dstFrameP->frameRect
  431.     if (dstBlitRect.top < dstFrameP->frameRect.top)
  432.     {
  433.         topClip = dstFrameP->frameRect.top - dstBlitRect.top;
  434.         dstBlitRect.top = dstFrameP->frameRect.top;
  435.     }
  436.     
  437.     if (dstBlitRect.bottom > dstFrameP->frameRect.bottom)
  438.         bottomClip = dstBlitRect.bottom - dstFrameP->frameRect.bottom; 
  439.     
  440.     if (dstBlitRect.left < dstFrameP->frameRect.left)
  441.         leftClip = dstFrameP->frameRect.left - dstBlitRect.left;
  442.     
  443.     if (dstBlitRect.right > dstFrameP->frameRect.right)
  444.         rightClip = dstBlitRect.right - dstFrameP->frameRect.right;
  445.     
  446.     
  447.         // "Unclip" sprite if it was already clipped before this function was called
  448.     if (srcBlitRect.top > srcFrameP->frameRect.top)
  449.     {
  450.         topClip2 = srcBlitRect.top - srcFrameP->frameRect.top;
  451.         srcBlitRect.top = srcFrameP->frameRect.top;
  452.     }
  453.     
  454.     if (srcBlitRect.bottom < srcFrameP->frameRect.bottom)
  455.     {
  456.         bottomClip2 = srcFrameP->frameRect.bottom - srcBlitRect.bottom; 
  457.         srcBlitRect.bottom = srcFrameP->frameRect.bottom;
  458.         dstBlitRect.bottom += bottomClip2;
  459.     }
  460.  
  461.     if (srcBlitRect.left > srcFrameP->frameRect.left)
  462.     {
  463.         leftClip2 = srcBlitRect.left - srcFrameP->frameRect.left;
  464.         srcBlitRect.left = srcFrameP->frameRect.left;
  465.         dstBlitRect.left -= leftClip2;
  466.     }
  467.     
  468.     if (srcBlitRect.right < srcFrameP->frameRect.right)
  469.     {
  470.         rightClip2 = srcFrameP->frameRect.right - srcBlitRect.right; 
  471.         srcBlitRect.right = srcFrameP->frameRect.right;
  472.         dstBlitRect.right += rightClip2;
  473.     }    
  474.     
  475.     topClip += topClip2;
  476.     leftClip += leftClip2;
  477.     rightClip += rightClip2;
  478.     bottomClip += bottomClip2;
  479.     
  480.         
  481.         // Cache this value since it's used twice
  482.     srcBaseOffset = (srcFrameP->scanLinePtrArray[srcBlitRect.top - 
  483.             srcFrameP->frameRect.top]) + srcBlitRect.left;
  484.  
  485.     START_32_BIT_MODE
  486.     
  487.     PrecomputeLookupTable(
  488.             (srcBlitRect.right - srcBlitRect.left),
  489.             (dstBlitRect.right - dstBlitRect.left),
  490.             leftClip, 
  491.             rightClip);
  492.  
  493.  
  494.     BlitPixieMask8BitScaled(
  495.             // calculate the address of the first byte of the source
  496.         (unsigned char *)(srcFrameP->frameBaseAddr + srcBaseOffset),
  497.  
  498.             // calculate the address of the first byte of the destination
  499.         (unsigned char *)(dstFrameP->frameBaseAddr + 
  500.             (dstFrameP->scanLinePtrArray[dstBlitRect.top - dstFrameP->frameRect.top]) + 
  501.             dstBlitRect.left),
  502.  
  503.                 // calculate the address of the first byte of the mask
  504.         (unsigned char *)(srcFrameP->maskBaseAddr + srcBaseOffset),
  505.  
  506.             // calculate the number of rows to blit
  507.         (srcBlitRect.bottom - srcBlitRect.top),
  508.         (dstBlitRect.bottom - dstBlitRect.top) + topClip,
  509.         
  510.         srcFrameP->frameRowBytes,
  511.         dstFrameP->frameRowBytes,
  512.         
  513.             // clipping information
  514.         leftClip,
  515.         topClip,
  516.         bottomClip,
  517.                 
  518.             // are we blitting direct-to-screen?
  519.         dstFrameP->isWindowFrame
  520.     );
  521.  
  522.  
  523.     END_32_BIT_MODE
  524. }
  525.  
  526.  
  527. ///--------------------------------------------------------------------------------------
  528. //    BlitPixie8BitScaled
  529. ///--------------------------------------------------------------------------------------
  530.  
  531. void BlitPixie8BitScaled(
  532.     register unsigned char *srcPixelP,
  533.     register unsigned char *dstPixelP,
  534.     long srcRowsToCopy,
  535.     long dstRowsToCopy,
  536.     unsigned long srcOffset,
  537.     unsigned long dstOffset,
  538.     short leftClip,
  539.     short topClip,
  540.     short bottomClip,
  541.     Boolean isBlittingToScreen)
  542. {
  543.     register unsigned char *startSrcPixelP;
  544.     register unsigned char *startDstPixelP;
  545.     long    verticalEps;
  546.     short    curRow, numRowsToCopy;
  547.     
  548.     startSrcPixelP = srcPixelP;
  549.     startDstPixelP = dstPixelP;
  550.  
  551.     if (srcRowsToCopy >= dstRowsToCopy)
  552.         verticalEps = srcRowsToCopy / 2;
  553.     else
  554.         verticalEps = -dstRowsToCopy / 2;
  555.     
  556.         // Clip off the top if necessary
  557.     for (curRow = 0; curRow < topClip; curRow++)
  558.     {
  559.         if (srcRowsToCopy >= dstRowsToCopy) 
  560.         {
  561.             while ((verticalEps * 2) <= srcRowsToCopy) 
  562.             {
  563.                     // shrink
  564.                 startSrcPixelP += srcOffset;
  565.                 verticalEps += dstRowsToCopy;
  566.             }
  567.             verticalEps -= srcRowsToCopy;
  568.         } 
  569.         else 
  570.         {
  571.                 // grow
  572.             verticalEps += srcRowsToCopy;
  573.             if ((verticalEps * 2) > dstRowsToCopy)  
  574.             {
  575.                 startSrcPixelP += srcOffset;
  576.                 verticalEps -= dstRowsToCopy;
  577.             }
  578.         }
  579.     }
  580.  
  581.         // Handle the bottom clip
  582.     numRowsToCopy = dstRowsToCopy - bottomClip;
  583.     
  584.         // Draw the thing
  585.     for (; curRow < numRowsToCopy; curRow++)
  586.     {
  587.         BlitScaledLine8Bit(startSrcPixelP + gSrcLeftClip, startDstPixelP + leftClip, 
  588.                 isBlittingToScreen);    
  589.         
  590.             // bump to next row    
  591.         startDstPixelP += dstOffset;
  592.  
  593.         if (srcRowsToCopy >= dstRowsToCopy) 
  594.         {
  595.             while ((verticalEps * 2) <= srcRowsToCopy)
  596.             {
  597.                     // shrink
  598.                 startSrcPixelP += srcOffset;
  599.                 verticalEps += dstRowsToCopy;
  600.             }
  601.             verticalEps -= srcRowsToCopy;
  602.         } 
  603.         else
  604.         {
  605.                 // grow
  606.             verticalEps += srcRowsToCopy;
  607.             if ((verticalEps * 2) > dstRowsToCopy) 
  608.             {
  609.                 startSrcPixelP += srcOffset;
  610.                 verticalEps -= dstRowsToCopy;
  611.             }
  612.         }
  613.     }
  614. }
  615.  
  616.  
  617. ///--------------------------------------------------------------------------------------
  618. //    BlitPixieMask8BitScaled
  619. ///--------------------------------------------------------------------------------------
  620.  
  621. void BlitPixieMask8BitScaled(
  622.     register unsigned char *srcPixelP,
  623.     register unsigned char *dstPixelP,
  624.     register unsigned char *maskPixelP,
  625.     long srcRowsToCopy,
  626.     long dstRowsToCopy,
  627.     unsigned long srcOffset,
  628.     unsigned long dstOffset,
  629.     short leftClip,
  630.     short topClip,
  631.     short bottomClip,
  632.     short isBlittingToScreen)
  633. {
  634.     register unsigned char *startSrcPixelP;
  635.     register unsigned char *startDstPixelP;
  636.     register unsigned char *startMaskPixelP;
  637.     long    verticalEps;
  638.     short    curRow, numRowsToCopy;
  639.     
  640.     startSrcPixelP = srcPixelP;
  641.     startDstPixelP = dstPixelP;
  642.     startMaskPixelP = maskPixelP;
  643.  
  644.     if (srcRowsToCopy >= dstRowsToCopy)
  645.         verticalEps = srcRowsToCopy / 2;
  646.     else
  647.         verticalEps = -dstRowsToCopy / 2;
  648.     
  649.         // Clip off the top if necessary
  650.     for (curRow = 0; curRow < topClip; curRow++)
  651.     {
  652.         if (srcRowsToCopy >= dstRowsToCopy) {
  653.             while ((verticalEps * 2) <= srcRowsToCopy) {
  654.                 // shrink
  655.                 startSrcPixelP += srcOffset;
  656.                 startMaskPixelP += srcOffset;
  657.                 verticalEps += dstRowsToCopy;
  658.             }
  659.             verticalEps -= srcRowsToCopy;
  660.         } else {
  661.             // grow
  662.             verticalEps += srcRowsToCopy;
  663.             if ((verticalEps * 2) > dstRowsToCopy)  {
  664.                 startSrcPixelP += srcOffset;
  665.                 startMaskPixelP += srcOffset;
  666.                 verticalEps -= dstRowsToCopy;
  667.             }
  668.         }
  669.     }
  670.  
  671.         // Handle the bottom clip
  672.     numRowsToCopy = dstRowsToCopy - bottomClip;
  673.     
  674.         // Draw the thing
  675.     for (; curRow < numRowsToCopy; curRow++)
  676.     {
  677.         BlitScaledMaskedLine8Bit(startSrcPixelP + gSrcLeftClip, startMaskPixelP + gSrcLeftClip,
  678.             startDstPixelP + leftClip, isBlittingToScreen);
  679.         
  680.             // bump to next row    
  681.         startDstPixelP += dstOffset;
  682.  
  683.         if (srcRowsToCopy >= dstRowsToCopy) {
  684.             while ((verticalEps * 2) <= srcRowsToCopy) {
  685.                 // shrink
  686.                 startSrcPixelP += srcOffset;
  687.                 startMaskPixelP += srcOffset;
  688.                 verticalEps += dstRowsToCopy;
  689.             }
  690.             verticalEps -= srcRowsToCopy;
  691.         } else {
  692.             // grow
  693.             verticalEps += srcRowsToCopy;
  694.             if ((verticalEps * 2) > dstRowsToCopy)  {
  695.                 startSrcPixelP += srcOffset;
  696.                 startMaskPixelP += srcOffset;
  697.                 verticalEps -= dstRowsToCopy;
  698.             }
  699.         }
  700.     }
  701. }
  702.  
  703.  
  704. ///--------------------------------------------------------------------------------------
  705. //    BlitScaledLine8Bit - it makes it slightly faster on 68k Macs to put this code in its
  706. //  own function, instead of placing it directly in BlitPixie8BitScaled. It goes the same
  707. //  speed on PPC. This must be because we're "breaking the cache" on 68k Macs otherwise.
  708. ///--------------------------------------------------------------------------------------
  709.  
  710. void BlitScaledLine8Bit(
  711.     register unsigned char *srcPixelP,
  712.     register unsigned char *dstPixelP,
  713.     Boolean weAreBlittingToScreen)
  714. {
  715.     register unsigned short *lookupArrayP;
  716.     short    numPixelsToCopy;
  717.  
  718.     lookupArrayP = gLookupArray;
  719.     
  720.     numPixelsToCopy = gNumPixelsToCopy;
  721.     
  722.         // The following code speeds up both 68k and PPC Macs when blitting directly to the
  723.         // screen, as well as 68k Macs slightly when blitting offscreen. (But not PPC
  724.         // when blitting offscreen)
  725.     if (weAreBlittingToScreen || !SW_PPC)
  726.     {
  727.         unsigned long    srcBuffer;
  728.         register unsigned char  *srcBufferPixelP;
  729.         
  730.         while (numPixelsToCopy >= 4) 
  731.         {
  732.                 // Get char pointer to our 4-byte buffer
  733.             srcBufferPixelP = (unsigned char *)&srcBuffer;
  734.             
  735.                 // Load 1st pixel into buffer
  736.             srcPixelP += *lookupArrayP;
  737.             *srcBufferPixelP++ = *srcPixelP;
  738.             lookupArrayP++;
  739.             
  740.                 // Load 2nd pixel into buffer
  741.             srcPixelP += *lookupArrayP;
  742.             *srcBufferPixelP++ = *srcPixelP;
  743.             lookupArrayP++;
  744.             
  745.                 // Load 3rd pixel into buffer
  746.             srcPixelP += *lookupArrayP;
  747.             *srcBufferPixelP++ = *srcPixelP;
  748.             lookupArrayP++;
  749.             
  750.                 // Load 4th pixel into buffer
  751.             srcPixelP += *lookupArrayP;
  752.             *srcBufferPixelP++ = *srcPixelP;
  753.             lookupArrayP++;
  754.             
  755.                 // Copy from our 4-byte buffer to the destination
  756.             *((unsigned long *) dstPixelP)++ = srcBuffer;
  757.             
  758.             numPixelsToCopy -= 4;
  759.         }
  760.     }
  761.  
  762.  
  763.         // This code draws the rest of the line that was not handled above on 68k Macs,
  764.         // or it draws the entire line on PowerMacs.
  765.     while (numPixelsToCopy--) 
  766.     {
  767.         srcPixelP += *lookupArrayP;
  768.         lookupArrayP++;
  769.         
  770.         *dstPixelP = *srcPixelP;
  771.         dstPixelP++;
  772.     }
  773. }
  774.  
  775.  
  776. ///--------------------------------------------------------------------------------------
  777. //    BlitScaledMaskedLine8Bit - it makes it slightly faster on 68k Macs to put this code in its
  778. //  own function, instead of placing it directly in BlitPixieMask8BitScaled. It goes the
  779. //    same speed on PPC. This must be because we're "breaking the cache" on 68k Macs otherwise.
  780. ///--------------------------------------------------------------------------------------
  781.  
  782. void BlitScaledMaskedLine8Bit(
  783.     register unsigned char *srcPixelP,
  784.     register unsigned char *maskPixelP,
  785.     register unsigned char *dstPixelP,
  786.     Boolean weAreBlittingToScreen)
  787. {
  788.     register unsigned short *lookupArrayP;
  789.     short    numPixelsToCopy;
  790.  
  791.     lookupArrayP = gLookupArray;
  792.     
  793.     numPixelsToCopy = gNumPixelsToCopy;
  794.     
  795.         // The following code speeds up both 68k and PPC Macs when blitting directly to the
  796.         // screen, as well as 68k Macs slightly when blitting offscreen. (But not PPC
  797.         // when blitting offscreen)
  798.     if (weAreBlittingToScreen || !SW_PPC)
  799.     {
  800.         unsigned long    srcBuffer, maskBuffer;
  801.         register unsigned char  *srcBufferPixelP, *maskBufferPixelP;
  802.         register unsigned long temp1;
  803.         
  804.         while (numPixelsToCopy >= 4) 
  805.         {
  806.                 // Get char pointers to our 4-byte buffers
  807.             srcBufferPixelP = (unsigned char *)&srcBuffer;
  808.             maskBufferPixelP = (unsigned char *)&maskBuffer;
  809.             
  810.                 // Load 1st pixel into buffer
  811.             srcPixelP += *lookupArrayP;
  812.             maskPixelP += *lookupArrayP;
  813.             *srcBufferPixelP++ = *srcPixelP;
  814.             *maskBufferPixelP++ = *maskPixelP;
  815.             lookupArrayP++;
  816.             
  817.                 // Load 2nd pixel into buffer
  818.             srcPixelP += *lookupArrayP;
  819.             maskPixelP += *lookupArrayP;
  820.             *srcBufferPixelP++ = *srcPixelP;
  821.             *maskBufferPixelP++ = *maskPixelP;
  822.             lookupArrayP++;
  823.             
  824.                 // Load 3rd pixel into buffer
  825.             srcPixelP += *lookupArrayP;
  826.             maskPixelP += *lookupArrayP;
  827.             *srcBufferPixelP++ = *srcPixelP;
  828.             *maskBufferPixelP++ = *maskPixelP;
  829.             lookupArrayP++;
  830.             
  831.                 // Load 4th pixel into buffer
  832.             srcPixelP += *lookupArrayP;
  833.             maskPixelP += *lookupArrayP;
  834.             *srcBufferPixelP = *srcPixelP;
  835.             *maskBufferPixelP = *maskPixelP;
  836.             lookupArrayP++;
  837.  
  838.                 // Copy from our 4-byte buffer to the destination
  839.             temp1 = *((unsigned long *) dstPixelP) & maskBuffer | srcBuffer;
  840.             *((unsigned long *) dstPixelP)++ = temp1;
  841.             
  842.             numPixelsToCopy -= 4;
  843.         }
  844.     }
  845.  
  846.         // This code draws the rest of the line that was not handled above on 68k Macs,
  847.         // or it draws the entire line on PowerMacs.
  848.     while (numPixelsToCopy--) 
  849.     {
  850.         srcPixelP += *lookupArrayP;
  851.         maskPixelP += *lookupArrayP;
  852.         
  853.         if (*maskPixelP == 0)
  854.             *dstPixelP = *srcPixelP;
  855.         
  856.         dstPixelP++;
  857.         lookupArrayP++;
  858.     }
  859. }
  860.  
  861.  
  862. #pragma mark ----------- 16 Bit Blitters -------------
  863.  
  864. ///--------------------------------------------------------------------------------------
  865. //    BlitPixie16BitScaledRectDrawProc - doesn't "unclip" the source rect, so it
  866. //    can be used directly by the user.
  867. ///--------------------------------------------------------------------------------------
  868.  
  869. SW_FUNC void BlitPixie16BitScaledRectDrawProc(
  870.     FramePtr srcFrameP,
  871.     FramePtr dstFrameP,
  872.     Rect* srcRect,
  873.     Rect* dstRect)
  874. {
  875.     Rect         srcBlitRect = *srcRect;
  876.     Rect         dstBlitRect = *dstRect;
  877.     short        topClip, rightClip, bottomClip, leftClip;
  878.     
  879.     SW_ASSERT(srcFrameP->isFrameLocked && dstFrameP->isFrameLocked);
  880.     SW_ASSERT(srcFrameP->frameDepth == 16 && dstFrameP->frameDepth == 16);
  881.  
  882.         // Make sure some part of the Sprite is inside the dstFrame
  883.     if (dstBlitRect.left >= dstFrameP->frameRect.right ||
  884.         dstBlitRect.right <= dstFrameP->frameRect.left ||
  885.         dstBlitRect.top >= dstFrameP->frameRect.bottom ||
  886.         dstBlitRect.bottom <= dstFrameP->frameRect.top )
  887.     {
  888.         return;
  889.     }
  890.  
  891.     topClip = rightClip = bottomClip = leftClip = 0;
  892.     
  893.         // Clip dstRect with dstFrameP->frameRect
  894.     if (dstBlitRect.top < dstFrameP->frameRect.top)
  895.     {
  896.         topClip = dstFrameP->frameRect.top - dstBlitRect.top;
  897.         dstBlitRect.top = dstFrameP->frameRect.top;
  898.     }
  899.     
  900.     if (dstBlitRect.bottom > dstFrameP->frameRect.bottom)
  901.         bottomClip = dstBlitRect.bottom - dstFrameP->frameRect.bottom; 
  902.     
  903.     if (dstBlitRect.left < dstFrameP->frameRect.left)
  904.         leftClip = dstFrameP->frameRect.left - dstBlitRect.left;
  905.     
  906.     if (dstBlitRect.right > dstFrameP->frameRect.right)
  907.         rightClip = dstBlitRect.right - dstFrameP->frameRect.right;
  908.     
  909.         
  910.     START_32_BIT_MODE
  911.     
  912.     PrecomputeLookupTable(
  913.         (srcBlitRect.right - srcBlitRect.left),
  914.         (dstBlitRect.right - dstBlitRect.left),
  915.         leftClip, 
  916.         rightClip);
  917.  
  918.  
  919.     BlitPixie16BitScaled(
  920.             // calculate the address of the first byte of the source
  921.         (unsigned short *)(srcFrameP->frameBaseAddr + 
  922.             (srcFrameP->scanLinePtrArray[srcBlitRect.top - srcFrameP->frameRect.top]) + 
  923.             (srcBlitRect.left << 1)),
  924.  
  925.             // calculate the address of the first byte of the destination
  926.         (unsigned short *)(dstFrameP->frameBaseAddr + 
  927.             (dstFrameP->scanLinePtrArray[dstBlitRect.top - dstFrameP->frameRect.top]) + 
  928.             (dstBlitRect.left << 1)),
  929.  
  930.             // calculate the number of rows to blit
  931.         srcBlitRect.bottom - srcBlitRect.top,
  932.         dstBlitRect.bottom - dstBlitRect.top + topClip,
  933.  
  934.             // for PPC, just frameRowBytes
  935.         srcFrameP->frameRowBytes,
  936.         dstFrameP->frameRowBytes,
  937.         
  938.             // clipping information
  939.         leftClip,
  940.         topClip,
  941.         bottomClip,
  942.                         
  943.             // are we blitting direct-to-screen?
  944.         dstFrameP->isWindowFrame
  945.     );
  946.  
  947.  
  948.     END_32_BIT_MODE
  949. }
  950.  
  951.  
  952. ///--------------------------------------------------------------------------------------
  953. //        BP16BitScaledSpriteRectDrawProc
  954. ///--------------------------------------------------------------------------------------
  955.  
  956. SW_FUNC void BP16BitScaledSpriteRectDrawProc(
  957.     FramePtr srcFrameP,
  958.     FramePtr dstFrameP,
  959.     Rect* srcRect,
  960.     Rect* dstRect)
  961. {
  962.     Rect         srcBlitRect = *srcRect;
  963.     Rect         dstBlitRect = *dstRect;
  964.     short        topClip, rightClip, bottomClip, leftClip;
  965.     short        topClip2, rightClip2, bottomClip2, leftClip2;
  966.     
  967.     SW_ASSERT(srcFrameP->isFrameLocked && dstFrameP->isFrameLocked);
  968.     SW_ASSERT(srcFrameP->frameDepth == 16 && dstFrameP->frameDepth == 16);
  969.  
  970.         // Make sure some part of the Sprite is inside the dstFrame
  971.     if (dstBlitRect.left >= dstFrameP->frameRect.right ||
  972.         dstBlitRect.right <= dstFrameP->frameRect.left ||
  973.         dstBlitRect.top >= dstFrameP->frameRect.bottom ||
  974.         dstBlitRect.bottom <= dstFrameP->frameRect.top )
  975.     {
  976.         return;
  977.     }
  978.  
  979.     topClip = rightClip = bottomClip = leftClip = 0;
  980.     topClip2 = rightClip2 = bottomClip2 = leftClip2 = 0;
  981.     
  982.         // Clip dstRect with dstFrameP->frameRect
  983.     if (dstBlitRect.top < dstFrameP->frameRect.top)
  984.     {
  985.         topClip = dstFrameP->frameRect.top - dstBlitRect.top;
  986.         dstBlitRect.top = dstFrameP->frameRect.top;
  987.     }
  988.     
  989.     if (dstBlitRect.bottom > dstFrameP->frameRect.bottom)
  990.         bottomClip = dstBlitRect.bottom - dstFrameP->frameRect.bottom; 
  991.     
  992.     if (dstBlitRect.left < dstFrameP->frameRect.left)
  993.         leftClip = dstFrameP->frameRect.left - dstBlitRect.left;
  994.     
  995.     if (dstBlitRect.right > dstFrameP->frameRect.right)
  996.         rightClip = dstBlitRect.right - dstFrameP->frameRect.right;
  997.     
  998.     
  999.         // "Unclip" sprite if it was already clipped before this function was called
  1000.     if (srcBlitRect.top > srcFrameP->frameRect.top)
  1001.     {
  1002.         topClip2 = srcBlitRect.top - srcFrameP->frameRect.top;
  1003.         srcBlitRect.top = srcFrameP->frameRect.top;
  1004.     }
  1005.     
  1006.     if (srcBlitRect.bottom < srcFrameP->frameRect.bottom)
  1007.     {
  1008.         bottomClip2 = srcFrameP->frameRect.bottom - srcBlitRect.bottom; 
  1009.         srcBlitRect.bottom = srcFrameP->frameRect.bottom;
  1010.         dstBlitRect.bottom += bottomClip2;
  1011.     }
  1012.  
  1013.     if (srcBlitRect.left > srcFrameP->frameRect.left)
  1014.     {
  1015.         leftClip2 = srcBlitRect.left - srcFrameP->frameRect.left;
  1016.         srcBlitRect.left = srcFrameP->frameRect.left;
  1017.         dstBlitRect.left -= leftClip2;
  1018.     }
  1019.     
  1020.     if (srcBlitRect.right < srcFrameP->frameRect.right)
  1021.     {
  1022.         rightClip2 = srcFrameP->frameRect.right - srcBlitRect.right; 
  1023.         srcBlitRect.right = srcFrameP->frameRect.right;
  1024.         dstBlitRect.right += rightClip2;
  1025.     }    
  1026.     
  1027.     topClip += topClip2;
  1028.     leftClip += leftClip2;
  1029.     rightClip += rightClip2;
  1030.     bottomClip += bottomClip2;
  1031.  
  1032.     START_32_BIT_MODE
  1033.     
  1034.     PrecomputeLookupTable(
  1035.         (srcBlitRect.right - srcBlitRect.left),
  1036.         (dstBlitRect.right - dstBlitRect.left),
  1037.         leftClip, 
  1038.         rightClip);
  1039.  
  1040.  
  1041.     BlitPixie16BitScaled(
  1042.             // calculate the address of the first byte of the source
  1043.         (unsigned short *)(srcFrameP->frameBaseAddr + 
  1044.             (srcFrameP->scanLinePtrArray[srcBlitRect.top - srcFrameP->frameRect.top]) + 
  1045.             (srcBlitRect.left << 1)),
  1046.  
  1047.             // calculate the address of the first byte of the destination
  1048.         (unsigned short *)(dstFrameP->frameBaseAddr + 
  1049.             (dstFrameP->scanLinePtrArray[dstBlitRect.top - dstFrameP->frameRect.top]) + 
  1050.             (dstBlitRect.left << 1)),
  1051.  
  1052.             // calculate the number of rows to blit
  1053.         srcBlitRect.bottom - srcBlitRect.top,
  1054.         dstBlitRect.bottom - dstBlitRect.top + topClip,
  1055.  
  1056.             // for PPC, just frameRowBytes
  1057.         srcFrameP->frameRowBytes,
  1058.         dstFrameP->frameRowBytes,
  1059.         
  1060.             // clipping information
  1061.         leftClip,
  1062.         topClip,
  1063.         bottomClip,
  1064.                         
  1065.             // are we blitting direct-to-screen?
  1066.         dstFrameP->isWindowFrame
  1067.     );
  1068.  
  1069.  
  1070.     END_32_BIT_MODE
  1071. }
  1072.  
  1073. ///--------------------------------------------------------------------------------------
  1074. //    BP16BitScaledSpriteMaskDrawProc
  1075. ///--------------------------------------------------------------------------------------
  1076.  
  1077. SW_FUNC void BP16BitScaledSpriteMaskDrawProc(
  1078.     FramePtr srcFrameP,
  1079.     FramePtr dstFrameP,
  1080.     Rect *srcRect,
  1081.     Rect *dstRect)
  1082. {
  1083.     Rect dstBlitRect = *dstRect;
  1084.     Rect srcBlitRect = *srcRect;
  1085.     unsigned long         srcBaseOffset;
  1086.     short        topClip, rightClip, bottomClip, leftClip;
  1087.     short        topClip2, rightClip2, bottomClip2, leftClip2;
  1088.     
  1089.     SW_ASSERT(srcFrameP->isFrameLocked && dstFrameP->isFrameLocked);
  1090.     SW_ASSERT(srcFrameP->frameDepth == 16 && dstFrameP->frameDepth == 16);
  1091.     SW_ASSERT(srcFrameP->maskPort != NULL);
  1092.  
  1093.         // Make sure some part of the Sprite is inside the dstFrame
  1094.     if (dstBlitRect.left >= dstFrameP->frameRect.right ||
  1095.         dstBlitRect.right <= dstFrameP->frameRect.left ||
  1096.         dstBlitRect.top >= dstFrameP->frameRect.bottom ||
  1097.         dstBlitRect.bottom <= dstFrameP->frameRect.top )
  1098.     {
  1099.         return;
  1100.     }
  1101.  
  1102.     topClip = rightClip = bottomClip = leftClip = 0;
  1103.     topClip2 = rightClip2 = bottomClip2 = leftClip2 = 0;
  1104.     
  1105.         // Clip dstRect with dstFrameP->frameRect
  1106.     if (dstBlitRect.top < dstFrameP->frameRect.top)
  1107.     {
  1108.         topClip = dstFrameP->frameRect.top - dstBlitRect.top;
  1109.         dstBlitRect.top = dstFrameP->frameRect.top;
  1110.     }
  1111.     
  1112.     if (dstBlitRect.bottom > dstFrameP->frameRect.bottom)
  1113.         bottomClip = dstBlitRect.bottom - dstFrameP->frameRect.bottom; 
  1114.     
  1115.     if (dstBlitRect.left < dstFrameP->frameRect.left)
  1116.         leftClip = dstFrameP->frameRect.left - dstBlitRect.left;
  1117.     
  1118.     if (dstBlitRect.right > dstFrameP->frameRect.right)
  1119.         rightClip = dstBlitRect.right - dstFrameP->frameRect.right;
  1120.     
  1121.     
  1122.         // "Unclip" sprite if it was already clipped before this function was called
  1123.     if (srcBlitRect.top > srcFrameP->frameRect.top)
  1124.     {
  1125.         topClip2 = srcBlitRect.top - srcFrameP->frameRect.top;
  1126.         srcBlitRect.top = srcFrameP->frameRect.top;
  1127.     }
  1128.     
  1129.     if (srcBlitRect.bottom < srcFrameP->frameRect.bottom)
  1130.     {
  1131.         bottomClip2 = srcFrameP->frameRect.bottom - srcBlitRect.bottom; 
  1132.         srcBlitRect.bottom = srcFrameP->frameRect.bottom;
  1133.         dstBlitRect.bottom += bottomClip2;
  1134.     }
  1135.  
  1136.     if (srcBlitRect.left > srcFrameP->frameRect.left)
  1137.     {
  1138.         leftClip2 = srcBlitRect.left - srcFrameP->frameRect.left;
  1139.         srcBlitRect.left = srcFrameP->frameRect.left;
  1140.         dstBlitRect.left -= leftClip2;
  1141.     }
  1142.     
  1143.     if (srcBlitRect.right < srcFrameP->frameRect.right)
  1144.     {
  1145.         rightClip2 = srcFrameP->frameRect.right - srcBlitRect.right; 
  1146.         srcBlitRect.right = srcFrameP->frameRect.right;
  1147.         dstBlitRect.right += rightClip2;
  1148.     }    
  1149.     
  1150.     topClip += topClip2;
  1151.     leftClip += leftClip2;
  1152.     rightClip += rightClip2;
  1153.     bottomClip += bottomClip2;
  1154.         
  1155.     // calculate the offset to the first byte of the source
  1156.     srcBaseOffset = srcFrameP->scanLinePtrArray[srcBlitRect.top - 
  1157.         srcFrameP->frameRect.top] + (srcBlitRect.left << 1);
  1158.  
  1159.     START_32_BIT_MODE
  1160.     
  1161.     PrecomputeLookupTable(
  1162.         (srcBlitRect.right - srcBlitRect.left),
  1163.         (dstBlitRect.right - dstBlitRect.left),
  1164.         leftClip, 
  1165.         rightClip);
  1166.  
  1167.  
  1168.     BlitPixieMask16BitScaled(
  1169.             // calculate the address of the first byte of the source
  1170.         (unsigned short *)(srcFrameP->frameBaseAddr + srcBaseOffset),
  1171.  
  1172.             // calculate the address of the first byte of the destination
  1173.         (unsigned short *)(dstFrameP->frameBaseAddr + 
  1174.             (dstFrameP->scanLinePtrArray[dstBlitRect.top - dstFrameP->frameRect.top]) + 
  1175.             (dstBlitRect.left << 1)),
  1176.  
  1177.             // calculate the address of the first byte of the mask
  1178.         (unsigned short *)(srcFrameP->maskBaseAddr + srcBaseOffset),
  1179.  
  1180.             // calculate the number of rows to blit
  1181.         srcBlitRect.bottom - srcBlitRect.top,
  1182.         dstBlitRect.bottom - dstBlitRect.top + topClip,  
  1183.  
  1184.         srcFrameP->frameRowBytes,
  1185.         dstFrameP->frameRowBytes,
  1186.         
  1187.             // clipping information
  1188.         leftClip,
  1189.         topClip,
  1190.         bottomClip
  1191.     );
  1192.     
  1193.  
  1194.     END_32_BIT_MODE
  1195. }
  1196.  
  1197.  
  1198. ///--------------------------------------------------------------------------------------
  1199. //    BlitPixie16BitScaled
  1200. ///--------------------------------------------------------------------------------------
  1201.  
  1202. void BlitPixie16BitScaled(
  1203.     unsigned short *srcPixelP,
  1204.     unsigned short *dstPixelP,
  1205.     register long srcRowsToCopy,
  1206.     register long dstRowsToCopy,
  1207.     register unsigned long srcOffset,
  1208.     register unsigned long dstOffset,
  1209.     short leftClip,
  1210.     short topClip,
  1211.     short bottomClip,
  1212.     short isBlittingToScreen)
  1213. {
  1214.     register unsigned short *startSrcPixelP;    // Stores the start of the
  1215.     register unsigned short *startDstPixelP;    // line currently being drawn
  1216.     long    verticalEps = 0;
  1217.     short    curRow, numRowsToCopy;
  1218.     
  1219.     startSrcPixelP = srcPixelP;
  1220.     startDstPixelP = dstPixelP;
  1221.     
  1222.     if (srcRowsToCopy >= dstRowsToCopy)
  1223.         verticalEps = srcRowsToCopy / 2;
  1224.     else
  1225.         verticalEps = -dstRowsToCopy / 2;
  1226.     
  1227.     // divide by 2 to get number of shorts from bytes
  1228.     srcOffset >>= 1;
  1229.     dstOffset >>= 1;
  1230.     
  1231.         // Clip off the top if necessary
  1232.     for (curRow = 0; curRow < topClip; curRow++)
  1233.     {
  1234.         if (srcRowsToCopy >= dstRowsToCopy) {
  1235.             while ((verticalEps * 2) <= srcRowsToCopy) {
  1236.                 // shrink
  1237.                 startSrcPixelP += srcOffset;    // Bump source to next row
  1238.                 verticalEps += dstRowsToCopy;
  1239.             }
  1240.             verticalEps -= srcRowsToCopy;
  1241.         } else {
  1242.             // grow
  1243.             verticalEps += srcRowsToCopy;
  1244.             if ((verticalEps * 2) > dstRowsToCopy)  {
  1245.                 startSrcPixelP += srcOffset;    // Bump source to next row
  1246.                 verticalEps -= dstRowsToCopy;
  1247.             }
  1248.         }
  1249.     }
  1250.  
  1251.         // Handle the bottom clip
  1252.     numRowsToCopy = dstRowsToCopy - bottomClip;
  1253.     
  1254.         // Draw the thing
  1255.     for (; curRow < numRowsToCopy; curRow++)
  1256.     {
  1257.         BlitScaledLine16Bit(startSrcPixelP + gSrcLeftClip, startDstPixelP + leftClip,
  1258.             isBlittingToScreen);
  1259.         
  1260.             // bump to next row    
  1261.         startDstPixelP += dstOffset;
  1262.  
  1263.         if (srcRowsToCopy >= dstRowsToCopy) {
  1264.             while ((verticalEps * 2) <= srcRowsToCopy) {
  1265.                 // shrink
  1266.                 startSrcPixelP += srcOffset;
  1267.                 verticalEps += dstRowsToCopy;
  1268.             }
  1269.             verticalEps -= srcRowsToCopy;
  1270.         } else {
  1271.             // grow
  1272.             verticalEps += srcRowsToCopy;
  1273.             if ((verticalEps * 2) > dstRowsToCopy)  {
  1274.                 startSrcPixelP += srcOffset;
  1275.                 verticalEps -= dstRowsToCopy;
  1276.             }
  1277.         }
  1278.     }
  1279. }
  1280.  
  1281.  
  1282. ///--------------------------------------------------------------------------------------
  1283. //    BlitPixieMask16BitScaled
  1284. ///--------------------------------------------------------------------------------------
  1285.  
  1286. void BlitPixieMask16BitScaled(
  1287.     unsigned short *srcPixelP,
  1288.     unsigned short *dstPixelP,
  1289.     unsigned short *maskPixelP,
  1290.     register long srcRowsToCopy,
  1291.     register long dstRowsToCopy,
  1292.     register unsigned long srcOffset,
  1293.     register unsigned long dstOffset,
  1294.     short leftClip,
  1295.     short topClip,
  1296.     short bottomClip)
  1297. {
  1298.     register unsigned short *startSrcPixelP;
  1299.     register unsigned short *startDstPixelP;
  1300.     register unsigned short *startMaskPixelP;
  1301.     long    verticalEps = 0;
  1302.     short    curRow, numRowsToCopy;
  1303.     
  1304.     startSrcPixelP = srcPixelP;
  1305.     startDstPixelP = dstPixelP;
  1306.     startMaskPixelP = maskPixelP;
  1307.     
  1308.     if (srcRowsToCopy >= dstRowsToCopy)
  1309.         verticalEps = srcRowsToCopy / 2;
  1310.     else
  1311.         verticalEps = -dstRowsToCopy / 2;
  1312.  
  1313.     // divide by 2 to get number of shorts from bytes
  1314.     srcOffset >>= 1;
  1315.     dstOffset >>= 1;
  1316.     
  1317.         // Clip off the top if necessary
  1318.     for (curRow = 0; curRow < topClip; curRow++)
  1319.     {
  1320.         if (srcRowsToCopy >= dstRowsToCopy) {
  1321.             while ((verticalEps * 2) <= srcRowsToCopy) {
  1322.                 // shrink
  1323.                 startSrcPixelP += srcOffset;
  1324.                 startMaskPixelP += srcOffset;
  1325.                 verticalEps += dstRowsToCopy;
  1326.             }
  1327.             verticalEps -= srcRowsToCopy;
  1328.         } else {
  1329.             // grow
  1330.             verticalEps += srcRowsToCopy;
  1331.             if ((verticalEps * 2) > dstRowsToCopy)  {
  1332.                 startSrcPixelP += srcOffset;
  1333.                 startMaskPixelP += srcOffset;
  1334.                 verticalEps -= dstRowsToCopy;
  1335.             }
  1336.         }
  1337.     }
  1338.  
  1339.         // Handle the bottom clip
  1340.     numRowsToCopy = dstRowsToCopy - bottomClip;
  1341.     
  1342.         // Draw the thing
  1343.     for (; curRow < numRowsToCopy; curRow++)
  1344.     {
  1345.         BlitScaledMaskedLine16Bit(startSrcPixelP + gSrcLeftClip, startMaskPixelP + gSrcLeftClip,
  1346.             startDstPixelP + leftClip);
  1347.         
  1348.             // bump to next row    
  1349.         startDstPixelP += dstOffset;
  1350.  
  1351.         if (srcRowsToCopy >= dstRowsToCopy) {
  1352.             while ((verticalEps * 2) <= srcRowsToCopy) {
  1353.                 // shrink
  1354.                 startSrcPixelP += srcOffset;
  1355.                 startMaskPixelP += srcOffset;
  1356.                 verticalEps += dstRowsToCopy;
  1357.             }
  1358.             verticalEps -= srcRowsToCopy;
  1359.         } else {
  1360.             // grow
  1361.             verticalEps += srcRowsToCopy;
  1362.             if ((verticalEps * 2) > dstRowsToCopy)  {
  1363.                 startSrcPixelP += srcOffset;
  1364.                 startMaskPixelP += srcOffset;
  1365.                 verticalEps -= dstRowsToCopy;
  1366.             }
  1367.         }
  1368.     }
  1369. }
  1370.  
  1371.  
  1372. ///--------------------------------------------------------------------------------------
  1373. //    BlitScaledLine16Bit - it makes it slightly faster on 68k Macs to put this code in its
  1374. //  own function, instead of placing it directly in BlitPixie16BitScaled. It goes the
  1375. //    same speed on PPC. This must be because we're "breaking the cache" on 68k Macs otherwise.
  1376. ///--------------------------------------------------------------------------------------
  1377.  
  1378. void BlitScaledLine16Bit(
  1379.     register unsigned short *srcPixelP,
  1380.     register unsigned short *dstPixelP,
  1381.     Boolean weAreBlittingToScreen)
  1382. {
  1383.     register unsigned short *lookupArrayP;
  1384.     short    numPixelsToCopy;
  1385.  
  1386.     lookupArrayP = gLookupArray;
  1387.     
  1388.     numPixelsToCopy = gNumPixelsToCopy;
  1389.  
  1390.         // The following code speeds up direct-to-screen blits, since we can make maximum
  1391.         // use of the bus.
  1392.     if (weAreBlittingToScreen)
  1393.     {
  1394.         unsigned long    srcBuffer;
  1395.         register unsigned short  *srcBufferPixelP;
  1396.         
  1397.         
  1398.         while (numPixelsToCopy >= 2) 
  1399.         {
  1400.                 // Get char pointers to our 4-byte buffers
  1401.             srcBufferPixelP = (unsigned short *)&srcBuffer;
  1402.             
  1403.                 // Load 1st pixel into buffer
  1404.             srcPixelP += *lookupArrayP;
  1405.             *srcBufferPixelP++ = *srcPixelP;
  1406.             lookupArrayP++;
  1407.             
  1408.                 // Load 2nd pixel into buffer
  1409.             srcPixelP += *lookupArrayP;
  1410.             *srcBufferPixelP = *srcPixelP;
  1411.             lookupArrayP++;
  1412.  
  1413.                 // Copy from our 4-byte buffer to the destination
  1414.             *((unsigned long *) dstPixelP)++ = srcBuffer;
  1415.             
  1416.             numPixelsToCopy -= 2;
  1417.         }
  1418.     }
  1419.     
  1420.  
  1421.         // Finish any part of the line not drawn above, or draw the entire line if necessary
  1422.     while (numPixelsToCopy--) 
  1423.     {
  1424.         srcPixelP += *lookupArrayP;
  1425.         lookupArrayP++;
  1426.         
  1427.         *dstPixelP = *srcPixelP;
  1428.         dstPixelP++;
  1429.     }
  1430. }
  1431.  
  1432.  
  1433. ///--------------------------------------------------------------------------------------
  1434. //    BlitScaledMaskedLine16Bit - it makes it slightly faster on 68k Macs to put this code in its
  1435. //  own function, instead of placing it directly in BlitPixieMask16BitScaled. It goes the
  1436. //    same speed on PPC. This must be because we're "breaking the cache" on 68k Macs otherwise.
  1437. ///--------------------------------------------------------------------------------------
  1438.  
  1439. void BlitScaledMaskedLine16Bit(
  1440.     register unsigned short *srcPixelP,
  1441.     register unsigned short *maskPixelP,
  1442.     register unsigned short *dstPixelP)
  1443. {
  1444.     register unsigned short *lookupArrayP;
  1445.     register short            numPixelsToCopy;
  1446.  
  1447.     lookupArrayP = gLookupArray;
  1448.     
  1449.     numPixelsToCopy = gNumPixelsToCopy;
  1450.  
  1451.         // Draw the line
  1452.     while (numPixelsToCopy--) 
  1453.     {
  1454.         srcPixelP += *lookupArrayP;
  1455.         maskPixelP += *lookupArrayP;
  1456.         
  1457.         if (*maskPixelP == 0)
  1458.             *dstPixelP = *srcPixelP;
  1459.         
  1460.         dstPixelP++;
  1461.         lookupArrayP++;
  1462.     }
  1463. }
  1464.  
  1465. #pragma mark ----------- 32 Bit Blitters -------------
  1466.  
  1467. ///--------------------------------------------------------------------------------------
  1468. //    BlitPixie32BitScaledRectDrawProc - doesn't "unclip" the source rect, so it
  1469. //    can be used directly by the user.
  1470. ///--------------------------------------------------------------------------------------
  1471.  
  1472. SW_FUNC void BlitPixie32BitScaledRectDrawProc(
  1473.     FramePtr srcFrameP,
  1474.     FramePtr dstFrameP,
  1475.     Rect* srcRect,
  1476.     Rect* dstRect)
  1477. {
  1478.     Rect         srcBlitRect = *srcRect;
  1479.     Rect         dstBlitRect = *dstRect;
  1480.     short        topClip, rightClip, bottomClip, leftClip;
  1481.     
  1482.     SW_ASSERT(srcFrameP->isFrameLocked && dstFrameP->isFrameLocked);
  1483.     SW_ASSERT(srcFrameP->frameDepth == 32 && dstFrameP->frameDepth == 32);
  1484.  
  1485.         // Make sure some part of the Sprite is inside the dstFrame
  1486.     if (dstBlitRect.left >= dstFrameP->frameRect.right ||
  1487.         dstBlitRect.right <= dstFrameP->frameRect.left ||
  1488.         dstBlitRect.top >= dstFrameP->frameRect.bottom ||
  1489.         dstBlitRect.bottom <= dstFrameP->frameRect.top )
  1490.     {
  1491.         return;
  1492.     }
  1493.  
  1494.     topClip = rightClip = bottomClip = leftClip = 0;
  1495.     
  1496.         // Clip dstRect with dstFrameP->frameRect
  1497.     if (dstBlitRect.top < dstFrameP->frameRect.top)
  1498.     {
  1499.         topClip = dstFrameP->frameRect.top - dstBlitRect.top;
  1500.         dstBlitRect.top = dstFrameP->frameRect.top;
  1501.     }
  1502.     
  1503.     if (dstBlitRect.bottom > dstFrameP->frameRect.bottom)
  1504.         bottomClip = dstBlitRect.bottom - dstFrameP->frameRect.bottom; 
  1505.     
  1506.     if (dstBlitRect.left < dstFrameP->frameRect.left)
  1507.         leftClip = dstFrameP->frameRect.left - dstBlitRect.left;
  1508.     
  1509.     if (dstBlitRect.right > dstFrameP->frameRect.right)
  1510.         rightClip = dstBlitRect.right - dstFrameP->frameRect.right;
  1511.     
  1512.         
  1513.     START_32_BIT_MODE
  1514.     
  1515.     PrecomputeLookupTable(
  1516.         (srcBlitRect.right - srcBlitRect.left),
  1517.         (dstBlitRect.right - dstBlitRect.left),
  1518.         leftClip, 
  1519.         rightClip);
  1520.  
  1521.  
  1522.     BlitPixie32BitScaled(
  1523.             // calculate the address of the first byte of the source
  1524.         (unsigned long *)(srcFrameP->frameBaseAddr + 
  1525.             (srcFrameP->scanLinePtrArray[srcBlitRect.top - srcFrameP->frameRect.top]) + 
  1526.             (srcBlitRect.left << 2)),
  1527.  
  1528.             // calculate the address of the first byte of the destination
  1529.         (unsigned long *)(dstFrameP->frameBaseAddr + 
  1530.             (dstFrameP->scanLinePtrArray[dstBlitRect.top - dstFrameP->frameRect.top]) + 
  1531.             (dstBlitRect.left << 2)),
  1532.  
  1533.             // calculate the number of rows to blit
  1534.         srcBlitRect.bottom - srcBlitRect.top,
  1535.         dstBlitRect.bottom - dstBlitRect.top + topClip,
  1536.  
  1537.             // for PPC, just frameRowBytes
  1538.         srcFrameP->frameRowBytes,
  1539.         dstFrameP->frameRowBytes,
  1540.         
  1541.             // clipping information
  1542.         leftClip,
  1543.         topClip,
  1544.         bottomClip,
  1545.                         
  1546.             // are we blitting direct-to-screen?
  1547.         dstFrameP->isWindowFrame
  1548.     );
  1549.  
  1550.  
  1551.     END_32_BIT_MODE
  1552. }
  1553.  
  1554.  
  1555. ///--------------------------------------------------------------------------------------
  1556. //        BP32BitScaledSpriteRectDrawProc
  1557. ///--------------------------------------------------------------------------------------
  1558.  
  1559. SW_FUNC void BP32BitScaledSpriteRectDrawProc(
  1560.     FramePtr srcFrameP,
  1561.     FramePtr dstFrameP,
  1562.     Rect* srcRect,
  1563.     Rect* dstRect)
  1564. {
  1565.     Rect         srcBlitRect = *srcRect;
  1566.     Rect         dstBlitRect = *dstRect;
  1567.     short        topClip, rightClip, bottomClip, leftClip;
  1568.     short        topClip2, rightClip2, bottomClip2, leftClip2;
  1569.     
  1570.     SW_ASSERT(srcFrameP->isFrameLocked && dstFrameP->isFrameLocked);
  1571.     SW_ASSERT(srcFrameP->frameDepth == 32 && dstFrameP->frameDepth == 32);
  1572.  
  1573.         // Make sure some part of the Sprite is inside the dstFrame
  1574.     if (dstBlitRect.left >= dstFrameP->frameRect.right ||
  1575.         dstBlitRect.right <= dstFrameP->frameRect.left ||
  1576.         dstBlitRect.top >= dstFrameP->frameRect.bottom ||
  1577.         dstBlitRect.bottom <= dstFrameP->frameRect.top )
  1578.     {
  1579.         return;
  1580.     }
  1581.  
  1582.     topClip = rightClip = bottomClip = leftClip = 0;
  1583.     topClip2 = rightClip2 = bottomClip2 = leftClip2 = 0;
  1584.     
  1585.         // Clip dstRect with dstFrameP->frameRect
  1586.     if (dstBlitRect.top < dstFrameP->frameRect.top)
  1587.     {
  1588.         topClip = dstFrameP->frameRect.top - dstBlitRect.top;
  1589.         dstBlitRect.top = dstFrameP->frameRect.top;
  1590.     }
  1591.     
  1592.     if (dstBlitRect.bottom > dstFrameP->frameRect.bottom)
  1593.         bottomClip = dstBlitRect.bottom - dstFrameP->frameRect.bottom; 
  1594.     
  1595.     if (dstBlitRect.left < dstFrameP->frameRect.left)
  1596.         leftClip = dstFrameP->frameRect.left - dstBlitRect.left;
  1597.     
  1598.     if (dstBlitRect.right > dstFrameP->frameRect.right)
  1599.         rightClip = dstBlitRect.right - dstFrameP->frameRect.right;
  1600.     
  1601.     
  1602.         // "Unclip" sprite if it was already clipped before this function was called
  1603.     if (srcBlitRect.top > srcFrameP->frameRect.top)
  1604.     {
  1605.         topClip2 = srcBlitRect.top - srcFrameP->frameRect.top;
  1606.         srcBlitRect.top = srcFrameP->frameRect.top;
  1607.     }
  1608.     
  1609.     if (srcBlitRect.bottom < srcFrameP->frameRect.bottom)
  1610.     {
  1611.         bottomClip2 = srcFrameP->frameRect.bottom - srcBlitRect.bottom; 
  1612.         srcBlitRect.bottom = srcFrameP->frameRect.bottom;
  1613.         dstBlitRect.bottom += bottomClip2;
  1614.     }
  1615.  
  1616.     if (srcBlitRect.left > srcFrameP->frameRect.left)
  1617.     {
  1618.         leftClip2 = srcBlitRect.left - srcFrameP->frameRect.left;
  1619.         srcBlitRect.left = srcFrameP->frameRect.left;
  1620.         dstBlitRect.left -= leftClip2;
  1621.     }
  1622.     
  1623.     if (srcBlitRect.right < srcFrameP->frameRect.right)
  1624.     {
  1625.         rightClip2 = srcFrameP->frameRect.right - srcBlitRect.right; 
  1626.         srcBlitRect.right = srcFrameP->frameRect.right;
  1627.         dstBlitRect.right += rightClip2;
  1628.     }    
  1629.     
  1630.     topClip += topClip2;
  1631.     leftClip += leftClip2;
  1632.     rightClip += rightClip2;
  1633.     bottomClip += bottomClip2;
  1634.  
  1635.     START_32_BIT_MODE
  1636.     
  1637.     PrecomputeLookupTable(
  1638.         (srcBlitRect.right - srcBlitRect.left),
  1639.         (dstBlitRect.right - dstBlitRect.left),
  1640.         leftClip, 
  1641.         rightClip);
  1642.  
  1643.  
  1644.     BlitPixie32BitScaled(
  1645.             // calculate the address of the first byte of the source
  1646.         (unsigned long *)(srcFrameP->frameBaseAddr + 
  1647.             (srcFrameP->scanLinePtrArray[srcBlitRect.top - srcFrameP->frameRect.top]) + 
  1648.             (srcBlitRect.left << 2)),
  1649.  
  1650.             // calculate the address of the first byte of the destination
  1651.         (unsigned long *)(dstFrameP->frameBaseAddr + 
  1652.             (dstFrameP->scanLinePtrArray[dstBlitRect.top - dstFrameP->frameRect.top]) + 
  1653.             (dstBlitRect.left << 2)),
  1654.  
  1655.             // calculate the number of rows to blit
  1656.         srcBlitRect.bottom - srcBlitRect.top,
  1657.         dstBlitRect.bottom - dstBlitRect.top + topClip,
  1658.  
  1659.             // for PPC, just frameRowBytes
  1660.         srcFrameP->frameRowBytes,
  1661.         dstFrameP->frameRowBytes,
  1662.         
  1663.             // clipping information
  1664.         leftClip,
  1665.         topClip,
  1666.         bottomClip,
  1667.                         
  1668.             // are we blitting direct-to-screen?
  1669.         dstFrameP->isWindowFrame
  1670.     );
  1671.  
  1672.  
  1673.     END_32_BIT_MODE
  1674. }
  1675.  
  1676. ///--------------------------------------------------------------------------------------
  1677. //    BP32BitScaledSpriteMaskDrawProc
  1678. ///--------------------------------------------------------------------------------------
  1679.  
  1680. SW_FUNC void BP32BitScaledSpriteMaskDrawProc(
  1681.     FramePtr srcFrameP,
  1682.     FramePtr dstFrameP,
  1683.     Rect *srcRect,
  1684.     Rect *dstRect)
  1685. {
  1686.     Rect dstBlitRect = *dstRect;
  1687.     Rect srcBlitRect = *srcRect;
  1688.     unsigned long         srcBaseOffset;
  1689.     short        topClip, rightClip, bottomClip, leftClip;
  1690.     short        topClip2, rightClip2, bottomClip2, leftClip2;
  1691.     
  1692.     SW_ASSERT(srcFrameP->isFrameLocked && dstFrameP->isFrameLocked);
  1693.     SW_ASSERT(srcFrameP->frameDepth == 32 && dstFrameP->frameDepth == 32);
  1694.     SW_ASSERT(srcFrameP->maskPort != NULL);
  1695.  
  1696.         // Make sure some part of the Sprite is inside the dstFrame
  1697.     if (dstBlitRect.left >= dstFrameP->frameRect.right ||
  1698.         dstBlitRect.right <= dstFrameP->frameRect.left ||
  1699.         dstBlitRect.top >= dstFrameP->frameRect.bottom ||
  1700.         dstBlitRect.bottom <= dstFrameP->frameRect.top )
  1701.     {
  1702.         return;
  1703.     }
  1704.  
  1705.     topClip = rightClip = bottomClip = leftClip = 0;
  1706.     topClip2 = rightClip2 = bottomClip2 = leftClip2 = 0;
  1707.     
  1708.         // Clip dstRect with dstFrameP->frameRect
  1709.     if (dstBlitRect.top < dstFrameP->frameRect.top)
  1710.     {
  1711.         topClip = dstFrameP->frameRect.top - dstBlitRect.top;
  1712.         dstBlitRect.top = dstFrameP->frameRect.top;
  1713.     }
  1714.     
  1715.     if (dstBlitRect.bottom > dstFrameP->frameRect.bottom)
  1716.         bottomClip = dstBlitRect.bottom - dstFrameP->frameRect.bottom; 
  1717.     
  1718.     if (dstBlitRect.left < dstFrameP->frameRect.left)
  1719.         leftClip = dstFrameP->frameRect.left - dstBlitRect.left;
  1720.     
  1721.     if (dstBlitRect.right > dstFrameP->frameRect.right)
  1722.         rightClip = dstBlitRect.right - dstFrameP->frameRect.right;
  1723.     
  1724.     
  1725.         // "Unclip" sprite if it was already clipped before this function was called
  1726.     if (srcBlitRect.top > srcFrameP->frameRect.top)
  1727.     {
  1728.         topClip2 = srcBlitRect.top - srcFrameP->frameRect.top;
  1729.         srcBlitRect.top = srcFrameP->frameRect.top;
  1730.     }
  1731.     
  1732.     if (srcBlitRect.bottom < srcFrameP->frameRect.bottom)
  1733.     {
  1734.         bottomClip2 = srcFrameP->frameRect.bottom - srcBlitRect.bottom; 
  1735.         srcBlitRect.bottom = srcFrameP->frameRect.bottom;
  1736.         dstBlitRect.bottom += bottomClip2;
  1737.     }
  1738.  
  1739.     if (srcBlitRect.left > srcFrameP->frameRect.left)
  1740.     {
  1741.         leftClip2 = srcBlitRect.left - srcFrameP->frameRect.left;
  1742.         srcBlitRect.left = srcFrameP->frameRect.left;
  1743.         dstBlitRect.left -= leftClip2;
  1744.     }
  1745.     
  1746.     if (srcBlitRect.right < srcFrameP->frameRect.right)
  1747.     {
  1748.         rightClip2 = srcFrameP->frameRect.right - srcBlitRect.right; 
  1749.         srcBlitRect.right = srcFrameP->frameRect.right;
  1750.         dstBlitRect.right += rightClip2;
  1751.     }    
  1752.     
  1753.     topClip += topClip2;
  1754.     leftClip += leftClip2;
  1755.     rightClip += rightClip2;
  1756.     bottomClip += bottomClip2;
  1757.         
  1758.     // calculate the offset to the first byte of the source
  1759.     srcBaseOffset = srcFrameP->scanLinePtrArray[srcBlitRect.top - 
  1760.         srcFrameP->frameRect.top] + (srcBlitRect.left << 2);
  1761.  
  1762.     START_32_BIT_MODE
  1763.     
  1764.     PrecomputeLookupTable(
  1765.         (srcBlitRect.right - srcBlitRect.left),
  1766.         (dstBlitRect.right - dstBlitRect.left),
  1767.         leftClip, 
  1768.         rightClip);
  1769.  
  1770.  
  1771.     BlitPixieMask32BitScaled(
  1772.             // calculate the address of the first byte of the source
  1773.         (unsigned long *)(srcFrameP->frameBaseAddr + srcBaseOffset),
  1774.  
  1775.             // calculate the address of the first byte of the destination
  1776.         (unsigned long *)(dstFrameP->frameBaseAddr + 
  1777.             (dstFrameP->scanLinePtrArray[dstBlitRect.top - dstFrameP->frameRect.top]) + 
  1778.             (dstBlitRect.left << 2)),
  1779.  
  1780.             // calculate the address of the first byte of the mask
  1781.         (unsigned long *)(srcFrameP->maskBaseAddr + srcBaseOffset),
  1782.  
  1783.             // calculate the number of rows to blit
  1784.         srcBlitRect.bottom - srcBlitRect.top,
  1785.         dstBlitRect.bottom - dstBlitRect.top + topClip,  
  1786.  
  1787.         srcFrameP->frameRowBytes,
  1788.         dstFrameP->frameRowBytes,
  1789.         
  1790.             // clipping information
  1791.         leftClip,
  1792.         topClip,
  1793.         bottomClip
  1794.     );
  1795.     
  1796.  
  1797.     END_32_BIT_MODE
  1798. }
  1799.  
  1800.  
  1801. ///--------------------------------------------------------------------------------------
  1802. //    BlitPixie32BitScaled
  1803. ///--------------------------------------------------------------------------------------
  1804.  
  1805. void BlitPixie32BitScaled(
  1806.     unsigned long *srcPixelP,
  1807.     unsigned long *dstPixelP,
  1808.     register long srcRowsToCopy,
  1809.     register long dstRowsToCopy,
  1810.     register unsigned long srcOffset,
  1811.     register unsigned long dstOffset,
  1812.     short leftClip,
  1813.     short topClip,
  1814.     short bottomClip,
  1815.     short isBlittingToScreen)
  1816. {
  1817.     register unsigned long *startSrcPixelP;    // Stores the start of the
  1818.     register unsigned long *startDstPixelP;    // line currently being drawn
  1819.     long    verticalEps = 0;
  1820.     short    curRow, numRowsToCopy;
  1821.     
  1822.     startSrcPixelP = srcPixelP;
  1823.     startDstPixelP = dstPixelP;
  1824.     
  1825.     if (srcRowsToCopy >= dstRowsToCopy)
  1826.         verticalEps = srcRowsToCopy / 2;
  1827.     else
  1828.         verticalEps = -dstRowsToCopy / 2;
  1829.     
  1830.     // divide by 4 to get number of longs from bytes
  1831.     srcOffset >>= 2;
  1832.     dstOffset >>= 2;
  1833.     
  1834.         // Clip off the top if necessary
  1835.     for (curRow = 0; curRow < topClip; curRow++)
  1836.     {
  1837.         if (srcRowsToCopy >= dstRowsToCopy) {
  1838.             while ((verticalEps * 2) <= srcRowsToCopy) {
  1839.                 // shrink
  1840.                 startSrcPixelP += srcOffset;    // Bump source to next row
  1841.                 verticalEps += dstRowsToCopy;
  1842.             }
  1843.             verticalEps -= srcRowsToCopy;
  1844.         } else {
  1845.             // grow
  1846.             verticalEps += srcRowsToCopy;
  1847.             if ((verticalEps * 2) > dstRowsToCopy)  {
  1848.                 startSrcPixelP += srcOffset;    // Bump source to next row
  1849.                 verticalEps -= dstRowsToCopy;
  1850.             }
  1851.         }
  1852.     }
  1853.  
  1854.         // Handle the bottom clip
  1855.     numRowsToCopy = dstRowsToCopy - bottomClip;
  1856.     
  1857.         // Draw the thing
  1858.     for (; curRow < numRowsToCopy; curRow++)
  1859.     {
  1860.         BlitScaledLine32Bit(startSrcPixelP + gSrcLeftClip, startDstPixelP + leftClip,
  1861.             isBlittingToScreen);
  1862.         
  1863.             // bump to next row    
  1864.         startDstPixelP += dstOffset;
  1865.  
  1866.         if (srcRowsToCopy >= dstRowsToCopy) {
  1867.             while ((verticalEps * 2) <= srcRowsToCopy) {
  1868.                 // shrink
  1869.                 startSrcPixelP += srcOffset;
  1870.                 verticalEps += dstRowsToCopy;
  1871.             }
  1872.             verticalEps -= srcRowsToCopy;
  1873.         } else {
  1874.             // grow
  1875.             verticalEps += srcRowsToCopy;
  1876.             if ((verticalEps * 2) > dstRowsToCopy)  {
  1877.                 startSrcPixelP += srcOffset;
  1878.                 verticalEps -= dstRowsToCopy;
  1879.             }
  1880.         }
  1881.     }
  1882. }
  1883.  
  1884.  
  1885. ///--------------------------------------------------------------------------------------
  1886. //    BlitPixieMask32BitScaled
  1887. ///--------------------------------------------------------------------------------------
  1888.  
  1889. void BlitPixieMask32BitScaled(
  1890.     unsigned long *srcPixelP,
  1891.     unsigned long *dstPixelP,
  1892.     unsigned long *maskPixelP,
  1893.     register long srcRowsToCopy,
  1894.     register long dstRowsToCopy,
  1895.     register unsigned long srcOffset,
  1896.     register unsigned long dstOffset,
  1897.     short leftClip,
  1898.     short topClip,
  1899.     short bottomClip)
  1900. {
  1901.     register unsigned long *startSrcPixelP;
  1902.     register unsigned long *startDstPixelP;
  1903.     register unsigned long *startMaskPixelP;
  1904.     long    verticalEps = 0;
  1905.     short    curRow, numRowsToCopy;
  1906.     
  1907.     startSrcPixelP = srcPixelP;
  1908.     startDstPixelP = dstPixelP;
  1909.     startMaskPixelP = maskPixelP;
  1910.     
  1911.     if (srcRowsToCopy >= dstRowsToCopy)
  1912.         verticalEps = srcRowsToCopy / 2;
  1913.     else
  1914.         verticalEps = -dstRowsToCopy / 2;
  1915.  
  1916.     // divide by 4 to get number of longs from bytes
  1917.     srcOffset >>= 2;
  1918.     dstOffset >>= 2;
  1919.     
  1920.         // Clip off the top if necessary
  1921.     for (curRow = 0; curRow < topClip; curRow++)
  1922.     {
  1923.         if (srcRowsToCopy >= dstRowsToCopy) {
  1924.             while ((verticalEps * 2) <= srcRowsToCopy) {
  1925.                 // shrink
  1926.                 startSrcPixelP += srcOffset;
  1927.                 startMaskPixelP += srcOffset;
  1928.                 verticalEps += dstRowsToCopy;
  1929.             }
  1930.             verticalEps -= srcRowsToCopy;
  1931.         } else {
  1932.             // grow
  1933.             verticalEps += srcRowsToCopy;
  1934.             if ((verticalEps * 2) > dstRowsToCopy)  {
  1935.                 startSrcPixelP += srcOffset;
  1936.                 startMaskPixelP += srcOffset;
  1937.                 verticalEps -= dstRowsToCopy;
  1938.             }
  1939.         }
  1940.     }
  1941.  
  1942.         // Handle the bottom clip
  1943.     numRowsToCopy = dstRowsToCopy - bottomClip;
  1944.     
  1945.         // Draw the thing
  1946.     for (; curRow < numRowsToCopy; curRow++)
  1947.     {
  1948.         BlitScaledMaskedLine32Bit(startSrcPixelP + gSrcLeftClip, startMaskPixelP + gSrcLeftClip,
  1949.             startDstPixelP + leftClip);
  1950.         
  1951.             // bump to next row    
  1952.         startDstPixelP += dstOffset;
  1953.  
  1954.         if (srcRowsToCopy >= dstRowsToCopy) {
  1955.             while ((verticalEps * 2) <= srcRowsToCopy) {
  1956.                 // shrink
  1957.                 startSrcPixelP += srcOffset;
  1958.                 startMaskPixelP += srcOffset;
  1959.                 verticalEps += dstRowsToCopy;
  1960.             }
  1961.             verticalEps -= srcRowsToCopy;
  1962.         } else {
  1963.             // grow
  1964.             verticalEps += srcRowsToCopy;
  1965.             if ((verticalEps * 2) > dstRowsToCopy)  {
  1966.                 startSrcPixelP += srcOffset;
  1967.                 startMaskPixelP += srcOffset;
  1968.                 verticalEps -= dstRowsToCopy;
  1969.             }
  1970.         }
  1971.     }
  1972. }
  1973.  
  1974.  
  1975. ///--------------------------------------------------------------------------------------
  1976. //    BlitScaledLine32Bit - it makes it slightly faster on 68k Macs to put this code in its
  1977. //  own function, instead of placing it directly in BlitPixie32BitScaled. It goes the
  1978. //    same speed on PPC. This must be because we're "breaking the cache" on 68k Macs otherwise.
  1979. ///--------------------------------------------------------------------------------------
  1980.  
  1981. void BlitScaledLine32Bit(
  1982.     register unsigned long *srcPixelP,
  1983.     register unsigned long *dstPixelP,
  1984.     Boolean weAreBlittingToScreen)
  1985. {
  1986.     #pragma unused(weAreBlittingToScreen)
  1987.     register unsigned short *lookupArrayP;
  1988.     register short            numPixelsToCopy;
  1989.  
  1990.     lookupArrayP = gLookupArray;
  1991.     
  1992.     numPixelsToCopy = gNumPixelsToCopy;
  1993.  
  1994.         // Finish any part of the line not drawn above, or draw the entire line if necessary
  1995.     while (numPixelsToCopy--) 
  1996.     {
  1997.         srcPixelP += *lookupArrayP;
  1998.         lookupArrayP++;
  1999.         
  2000.         *dstPixelP = *srcPixelP;
  2001.         dstPixelP++;
  2002.     }
  2003. }
  2004.  
  2005.  
  2006. ///--------------------------------------------------------------------------------------
  2007. //    BlitScaledMaskedLine32Bit - it makes it slightly faster on 68k Macs to put this code in its
  2008. //  own function, instead of placing it directly in BlitPixieMask32BitScaled. It goes the
  2009. //    same speed on PPC. This must be because we're "breaking the cache" on 68k Macs otherwise.
  2010. ///--------------------------------------------------------------------------------------
  2011.  
  2012. void BlitScaledMaskedLine32Bit(
  2013.     register unsigned long *srcPixelP,
  2014.     register unsigned long *maskPixelP,
  2015.     register unsigned long *dstPixelP)
  2016. {
  2017.     register unsigned short *lookupArrayP;
  2018.     register short            numPixelsToCopy;
  2019.  
  2020.     lookupArrayP = gLookupArray;
  2021.     
  2022.     numPixelsToCopy = gNumPixelsToCopy;
  2023.  
  2024.         // Draw the line
  2025.     while (numPixelsToCopy--) 
  2026.     {
  2027.         srcPixelP += *lookupArrayP;
  2028.         maskPixelP += *lookupArrayP;
  2029.         
  2030.         if (*maskPixelP == 0)
  2031.             *dstPixelP = *srcPixelP;
  2032.         
  2033.         dstPixelP++;
  2034.         lookupArrayP++;
  2035.     }
  2036. }
  2037.  
  2038.  
  2039. #pragma mark ----------- Misc -------------
  2040. ///--------------------------------------------------------------------------------------
  2041. //    PrecomputeLookupTable - calculates the data used to speed up the scaling blitter
  2042. ///--------------------------------------------------------------------------------------
  2043.  
  2044. void PrecomputeLookupTable(
  2045.     register long srcNumPixelsPerRow,
  2046.     register long dstNumPixelsPerRow,
  2047.     short leftClip,
  2048.     short rightClip)
  2049. {
  2050.     register short    numDstPixelsToDraw, eps;
  2051.     register short    destIndex, srcIndex, srcAccum;
  2052.  
  2053.     if (srcNumPixelsPerRow >= dstNumPixelsPerRow)
  2054.     {
  2055.             // Shrink it. For now we don't do any pixel blending for this case.
  2056.         destIndex = 0;
  2057.         eps = srcNumPixelsPerRow / 2;
  2058.  
  2059.             // Clip off the left if necessary
  2060.         for (srcIndex = 0; destIndex < leftClip && srcIndex < srcNumPixelsPerRow; srcIndex++)
  2061.         {
  2062.             eps += dstNumPixelsPerRow;
  2063.             if ( (eps << 2) > srcNumPixelsPerRow ) 
  2064.             {
  2065.                 destIndex++;
  2066.                 eps -= srcNumPixelsPerRow;
  2067.             }
  2068.         }
  2069.         
  2070.             // Store the left clip of the source
  2071.         gSrcLeftClip = srcIndex;
  2072.         
  2073.             // Clip off the right
  2074.         numDstPixelsToDraw = dstNumPixelsPerRow - rightClip;
  2075.         
  2076.             // This lets us reset dstIndex to 0
  2077.         numDstPixelsToDraw -= destIndex;
  2078.         SW_ASSERT(numDstPixelsToDraw > 0);
  2079.         SW_ASSERT(numDstPixelsToDraw <= kMaxScaledWidth);
  2080.         
  2081.         gNumPixelsToCopy = numDstPixelsToDraw;
  2082.         destIndex = 0;
  2083.         srcAccum = 0;
  2084.         
  2085.             // Bresenham line draw
  2086.         while (srcIndex < srcNumPixelsPerRow && destIndex < numDstPixelsToDraw) 
  2087.         {
  2088.             eps += dstNumPixelsPerRow;
  2089.             if ( (eps << 1) > srcNumPixelsPerRow ) 
  2090.             {
  2091.                 gLookupArray[destIndex] = srcAccum;
  2092.                 destIndex++;
  2093.                 srcAccum = 0;
  2094.                 eps -= srcNumPixelsPerRow;
  2095.             }
  2096.             srcAccum++;
  2097.             srcIndex++;
  2098.         }
  2099.     }
  2100.     else
  2101.     {
  2102.             // Stretch It. For now we don't do any anti aliasing for this case.
  2103.         srcIndex = 0;
  2104.         eps = -dstNumPixelsPerRow / 2;
  2105.         
  2106.             // Clip off the left if necessary
  2107.         for (destIndex = 0; destIndex < leftClip; destIndex++)
  2108.         {
  2109.             eps += srcNumPixelsPerRow;
  2110.             if ( (eps << 1) > dstNumPixelsPerRow )
  2111.             {
  2112.                 srcIndex++;
  2113.                 eps -= dstNumPixelsPerRow;
  2114.             }
  2115.         }
  2116.         
  2117.             // Store the left clip of the source
  2118.         gSrcLeftClip = srcIndex;
  2119.         
  2120.             // Clip off the right
  2121.         numDstPixelsToDraw = dstNumPixelsPerRow - rightClip;
  2122.     
  2123.             // This lets us reset dstIndex to 0
  2124.         numDstPixelsToDraw -= destIndex;
  2125.         SW_ASSERT(numDstPixelsToDraw > 0);
  2126.         SW_ASSERT(numDstPixelsToDraw <= kMaxScaledWidth);
  2127.         
  2128.         gNumPixelsToCopy = numDstPixelsToDraw;
  2129.         destIndex = 0;
  2130.         srcAccum = 0;
  2131.         
  2132.             // Use Bresenham's line drawing algorithm to store the values in gLookupArray
  2133.         while (destIndex < numDstPixelsToDraw)
  2134.         {
  2135.             gLookupArray[destIndex] = srcAccum;
  2136.             eps += srcNumPixelsPerRow;
  2137.             if ( (eps << 1) > dstNumPixelsPerRow )
  2138.             {
  2139.                 srcIndex++;
  2140.                 srcAccum = 1;
  2141.                 eps -= dstNumPixelsPerRow;
  2142.             }
  2143.             else
  2144.                 srcAccum = 0;
  2145.             destIndex++;
  2146.         }
  2147.     }
  2148. }
  2149.  
  2150.